package org.jeecg.modules.miniAppCustomerEndPoint.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.miniAppCustomerEndPoint.entity.JxUserCouponDo;
import org.jeecg.modules.miniAppCustomerEndPoint.mapper.JxUserCouponMapper;
import org.jeecg.modules.miniAppCustomerEndPoint.utils.JxUserUtil;
import org.jeecg.modules.platformMasterEndPoint.entity.JxCouponDo;
import org.jeecg.modules.platformMasterEndPoint.mapper.JxCouponMapper;
import org.jeecg.modules.platformMasterEndPoint.utils.JxOrderUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Api(tags = "购物券")
@RestController
@RequestMapping("/jx/jxCoupon")
@Slf4j
public class JxCouponController {


    @Autowired
    private JxUserCouponMapper jxUserCouponMapper;

    @Autowired
    private JxCouponMapper jxCouponMapper;

    /**
     * 接口 1.23
     * 用户打开小程序后，通过此接口，验证用户是否已经领取过 “新手大礼包”
     * @return
     */
    @GetMapping("/checkNewUserCouponPackage")
    public Result<?> checkNewUserCouponPackage(
            HttpServletRequest request,
            @RequestParam(value = "userIdForDebug", required = false) String userIdForDebug,
            @RequestParam("siteId") String siteId) {

        String token = request.getHeader("X-Access-Token");
        String userId = JxUserUtil.getUserId(token, userIdForDebug);

        JSONObject resultData = new JSONObject();
        // 查询用户是否领取过新手大礼包券，券id是硬编码的，新手大礼包的券从表中查询到
        List<JxUserCouponDo> list2 = jxUserCouponMapper.selectList(
                new LambdaQueryWrapper<JxUserCouponDo>().
                        eq(JxUserCouponDo::getUserId, userId).
                        eq(JxUserCouponDo::getCouponId, "1743280504718401538"));
        if (list2 != null && list2.size() > 0) {
            resultData.put("received", 1);
            resultData.put("couponId", "");
            resultData.put("couponName", ""); // 优惠券显示的内容，用来显示在页面上，优惠券上，比如 "5元通用券"
            resultData.put("couponValue", 0); // 每个优惠券的面值，页面上不用显示
            resultData.put("amountPerUser", 0); // 优惠券个数
            resultData.put("msg", "用户已领取过新手大礼包，不需要再展示新手大礼包窗口");
        } else {
            List<JxCouponDo> list3 = jxCouponMapper.selectList(new LambdaQueryWrapper<JxCouponDo>().eq(JxCouponDo::getCouponName, "新手大礼包"));
            if (list3 != null && list3.size() > 0) {
                JxCouponDo couponInfo = list3.get(0);
                resultData.put("received", 0);
                resultData.put("couponId", couponInfo.getId());
                resultData.put("couponName", couponInfo.getCouponName()); // 优惠券显示的内容，用来显示在页面上，优惠券上，比如 "5元通用券"
                resultData.put("couponValue", couponInfo.getCouponValue()); // 每个优惠券的面值，页面上不用显示
                resultData.put("amountPerUser", couponInfo.getAmountPerUser()); // 优惠券个数

                resultData.put("msg", "用户未领取过新手大礼包，需要展示新手大礼包窗口");
            }
        }

        return Result.ok(resultData);
    }

    /**
     * 用户点击领取新手大礼包；一般新手大礼包都有多张券，因此，向 jx_user_coupons 表中添加多张记录；用户没使用一张，就将对应记录的 used 设置为1，标记为，该券已使用过了
     * @param userId
     * @param siteId
     * @param couponId
     * @return
     */
    @PostMapping("/receiveNewUserCouponPackage")
    public Result<?> receiveNewUserCouponPackage(
            HttpServletRequest request,
            @RequestParam(value = "userId", required = false) String userId,
            @RequestParam("siteId") String siteId,
            @RequestParam("couponId") String couponId) {
        String token = request.getHeader("X-Access-Token");
        String userId2 = JxUserUtil.getUserId(token, userId);
        JxCouponDo jxCouponDo = jxCouponMapper.selectById(couponId);
        for (int k = 0 ; k < jxCouponDo.getAmountPerUser(); k ++) {

            JxUserCouponDo userCouponDo = new JxUserCouponDo();
            userCouponDo.setCouponId(jxCouponDo.getId());
            userCouponDo.setSiteId(siteId);
            userCouponDo.setStoreId(jxCouponDo.getStoreIds());
            userCouponDo.setUserId(userId2);
            userCouponDo.setUsed((short)0);
            userCouponDo.setDelFlag((short)0);
            userCouponDo.setCreateTime(new Date());

            jxUserCouponMapper.insert(userCouponDo);
        }

        return Result.ok();
    }


    /**
     * 用户进入店铺后，点击店铺页面中的优惠券，领取优惠券
     * @return
     */
    @PostMapping("/receiveCoupon")
    public Result<?> receiveCoupon(
            HttpServletRequest request,
            @RequestBody() JSONObject requestBody,
            @RequestParam(value = "userId", required = false) String userId) {

        String siteId = requestBody.getString("siteId");
        String storeId = requestBody.getString("storeId");
        String couponId = requestBody.getString("couponId");
        String token = request.getHeader("X-Access-Token");
        String userId2 = JxUserUtil.getUserId(token, userId);
        // 查询用户已经领取的券中，是否有该站点，该店铺的优惠券
        List<JxUserCouponDo> receivedCoupons = jxUserCouponMapper.selectList(new LambdaQueryWrapper<JxUserCouponDo>()
                .eq(JxUserCouponDo::getSiteId,siteId)
                .eq(JxUserCouponDo::getUserId, userId2)
                .eq(JxUserCouponDo::getStoreId,storeId)
                .eq(JxUserCouponDo::getCouponId, couponId));
        // 正常情况当用户第一次领取某个店铺的某一张优惠券后，优惠券的状态将会变成不可领取，用户再次进入店铺，前端页面该优惠券将显示无法领取，无法点击，即使用户误触发点击，也不会调用接口
        // 该接口实现时，还是需要添加了 禁止重复领取相同优惠券的逻辑，前端做了 防止重复领取验证，后端也需要做验证
        if (receivedCoupons != null && receivedCoupons.size() > 0) {
            return Result.error("用户已经领取过了该优惠券，不能重复领取");
        }
        JxUserCouponDo userCouponDo = new JxUserCouponDo();
        userCouponDo.setSiteId(siteId);
        userCouponDo.setUserId(userId2);
        userCouponDo.setStoreId(storeId);
        userCouponDo.setCouponId(couponId);
        userCouponDo.setUsed((short)0);
        userCouponDo.setDelFlag((short)0);
        userCouponDo.setCreateTime(new Date());
        try{
            int insertCount = jxUserCouponMapper.insert(userCouponDo);
            if (insertCount == 1) {
                return Result.ok("优惠券领取成功");
            } else {
                return Result.error("优惠券领取失败，请联系后台技术人员进行处理");
            }
        } catch (Exception ex) {
            log.error("向用户优惠券表添加记录，领取优惠券sql异常， {}", ex);
            return Result.error("优惠券领取失败，出现异常，请联系后台技术人员进行处理");
        }
    }

    /**
     * 接口 1.22
     * 在购物车页面，为用户展示对用户而言，可以使用的最佳的购物券，规则是，挑选价格减免最多的优惠券
     * 挑选最佳优惠券时，与店铺无关，用户可能购买多个店铺的菜品，领取多个不同店铺的优惠券，此时只需要挑选面值最大的即可
     * @return 最佳优惠券，以及其他可以使用的优惠券供用户挑选
     */
    @GetMapping("/chooseBestCoupon")
    public Result<?> chooseBestCoupon(
            HttpServletRequest request,
            @RequestParam("siteId") String siteId,
            @RequestParam(value = "userId", required = false) String userId) {

        String token = request.getHeader("X-Access-Token");
        String userId2 = JxUserUtil.getUserId(token, userId);

        String nowDateTime = JxUserUtil.formateDateTimeYYYYMMDDHHMMSS(new Date());
        List<HashMap<String, Object>> list = jxUserCouponMapper.queryAllAvailableCoupons(siteId, userId2, nowDateTime);

        List<HashMap<String, Object>> formatedCoupons = new ArrayList<>();
        HashMap<String, Object> bestCoupon = new HashMap<String, Object>();
        int bestCouponValue = 0;
        for (int k = 0 ; k < list.size() ; k ++) {
            HashMap<String, Object> userCouponDetail = list.get(k);
            String receiveCouponId = (String)userCouponDetail.get("receiveCouponId");
            String couponId = (String)userCouponDetail.get("couponId");
            String couponName = (String)userCouponDetail.get("couponName");
            Integer couponValue = (Integer)userCouponDetail.get("couponValue");
            String expiredAt = JxUserUtil.localDateTime2YYYYMMDDHHMMSS((LocalDateTime)userCouponDetail.get("expiredAt"));

            if (couponValue > bestCouponValue) {
                bestCouponValue = couponValue;
                // recevieCouponId 是指用户领取券的记录id，平台创建优惠券时，通常某一种券会持续发放一段时间，该券的id是一样的，但是用户每天领取券时，在 jx_user_coupons中生成的 券领取id不同
                // 当使用券的时候，使用券id不能唯一区分；比如 某张券的有效期是 3天，用户周一领取一张，周二领取一张；此时 jx_user_coupons 表中两条记录的 coupon_id 一样，因此在使用时，
                // 当使用完一张，若根据 coupon_id 进行update，则两张券都会被标记为 已使用
                bestCoupon.put("receiveCouponId", receiveCouponId);
                bestCoupon.put("couponId", couponId);
                bestCoupon.put("couponName", couponName);
                bestCoupon.put("couponValue", couponValue);
                bestCoupon.put("expiredAt", expiredAt);
            }

            HashMap<String, Object> oneFormatedCoupon = new HashMap<String, Object>();
            // recevieCouponId 是指用户领取券的记录id，平台创建优惠券时，通常某一种券会持续发放一段时间，该券的id是一样的，但是用户每天领取券时，在 jx_user_coupons中生成的 券领取id不同
            // 当使用券的时候，使用券id不能唯一区分；比如 某张券的有效期是 3天，用户周一领取一张，周二领取一张；此时 jx_user_coupons 表中两条记录的 coupon_id 一样，因此在使用时，
            // 当使用完一张，若根据 coupon_id 进行update，则两张券都会被标记为 已使用
            oneFormatedCoupon.put("receiveCouponId", receiveCouponId);
            oneFormatedCoupon.put("couponId", couponId);
            oneFormatedCoupon.put("couponName", couponName);
            oneFormatedCoupon.put("couponValue", couponValue);
            oneFormatedCoupon.put("expiredAt", expiredAt);
            formatedCoupons.add(oneFormatedCoupon);
        }

        JSONObject resultData = new JSONObject();
        resultData.put("bestCoupon",bestCoupon);
        resultData.put("allCoupons", formatedCoupons);
        return Result.ok(resultData);
    }


    /**
     * 接口3.5 我的优惠券页面，查看未使用，已使用/已过期 优惠券
     * @param request
     * @param userIdForDebug
     * @param type
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("/queryUserCouponsByType")
    public Result<?> queryUserCouponsByType(
            HttpServletRequest request,
            @RequestParam(value = "userId", required = false) String userIdForDebug,
            @RequestParam("type") Integer type,
            @RequestParam("pageNo") Integer pageNo,
            @RequestParam("pageSize") Integer pageSize) {
        String token = request.getHeader("X-Access-Token");
        String userId = JxUserUtil.getUserId(token, userIdForDebug);

        JSONObject resultData = new JSONObject();
        Page<JxUserCouponDo> page = new Page(pageNo, pageSize);
        List<JSONObject> formatedCoupons = new ArrayList<>();
        if (type == 0) {
            Page<JxUserCouponDo> pageList = jxUserCouponMapper.selectPage(page,
                    new LambdaQueryWrapper<JxUserCouponDo>().eq(JxUserCouponDo::getUserId, userId)
                            .eq(JxUserCouponDo::getUsed, 0).eq(JxUserCouponDo::getDelFlag, 0));
            for (int k = 0 ; k < pageList.getRecords().size(); k ++) {
                String couponId = pageList.getRecords().get(k).getCouponId();
                JSONObject formatedCoupon = formateCoupon(couponId);
                if (formatedCoupon != null) {
                    formatedCoupons.add(formatedCoupon);
                } else {
                    log.error("无法找到id为{} 的券", couponId);
                    continue;
                }
            }
            resultData.put("unusedCoupons", formatedCoupons);
            resultData.put("totalCount", pageList.getTotal());
            resultData.put("pages", pageList.getPages());
            return Result.ok(resultData);
        } else {

            String nowDateTime = JxUserUtil.formateDateTimeYYYYMMDDHHMMSS(new Date());
            List<HashMap<String, Object>> list = jxUserCouponMapper.queryUsedOrExpiredCoupons(userId, nowDateTime, (pageNo - 1) * pageSize, pageSize);

            for (int k = 0 ; k < list.size(); k ++) {
                String couponId = (String)list.get(k).get("couponId");
                JSONObject formatedCoupon = formateCoupon(couponId);
                if (formatedCoupon != null) {
                    formatedCoupons.add(formatedCoupon);
                } else {
                    log.error("无法找到id为{} 的券", couponId);
                    continue;
                }
            }
            int totalCount = jxUserCouponMapper.queryUsedOrExpiredCouponsPageInfo(userId, nowDateTime);
            resultData.put("usedOrExpiredCoupons", formatedCoupons);
            resultData.put("totalCount", totalCount);
            int totalPages = totalCount / pageSize == 0 ? totalCount / pageSize : (totalCount / pageSize + 1);
            resultData.put("pages",totalPages );
        }

        return Result.ok(resultData);
    }

    private JSONObject formateCoupon(String couponId) {
        JSONObject formatedCoupon = new JSONObject();
        JxCouponDo jxCouponDo = jxCouponMapper.selectById(couponId);
        if (jxCouponDo != null) {
            jxCouponDo.getCouponName();
            // recevieCouponId 是指用户领取券的记录id，平台创建优惠券时，通常某一种券会持续发放一段时间，该券的id是一样的，但是用户每天领取券时，在 jx_user_coupons中生成的 券领取id不同
            // 当使用券的时候，使用券id不能唯一区分；比如 某张券的有效期是 3天，用户周一领取一张，周二领取一张；此时 jx_user_coupons 表中两条记录的 coupon_id 一样，因此在使用时，
            // 当使用完一张，若根据 coupon_id 进行update，则两张券都会被标记为 已使用
            formatedCoupon.put("receiveCouponId", jxCouponDo.getId());
            formatedCoupon.put("couponId", couponId);
            formatedCoupon.put("couponValue", jxCouponDo.getCouponValue());
            formatedCoupon.put("couponName", jxCouponDo.getCouponName());
            // 券 适用于那些店铺，* 表示所有店铺;
            if (jxCouponDo.getStoreIds().trim().equalsIgnoreCase("*")) {
                JSONArray allStores = new JSONArray();
                allStores.add("*");
                formatedCoupon.put("storeIds", allStores);
            } else {
                formatedCoupon.put("storeIds", JSONArray.parseArray(jxCouponDo.getStoreIds()));
            }
            formatedCoupon.put("expiredAt", jxCouponDo.getExpiredAt());
        } else {
            log.error("无法找到id为{} 的券", couponId);
            return null;
        }

        return formatedCoupon;
    }
}
